/**
 * Copyright (c) 2018, Alex. All rights reserved.
 */
package com.oschina.bottle.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.oschina.bottle.common.exception.BaseException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.BeanUtils;

/**
 * 封装jackson工具类
 *
 * @author <a href="mailto:zhongchao@gegejia.com">zhong</a>
 * @version 1.0 2018/1/20
 * @since 1.0
 */
public class JsonUtils {

    private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();


    /**
     * 将java对象转换为字符串
     *
     * @param data  待转换的对象
     * @return      输出字符串
     */
    public static String parse(Object data) {
        try {
            return OBJECT_MAPPER.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            throw new BaseException(e, "JSON convert fail");
        }
    }

    /**
     * 将字符串转换为java对象
     *
     * @param data      待转换的数据
     * @param clazz     目标类
     * @param <T>       泛型
     * @return          输出对象
     */
    public static <T> T parseObject(String data, Class<T> clazz) {
        try {
            return OBJECT_MAPPER.readValue(data, clazz);
        } catch (IOException e) {
            throw new BaseException(e, "JSON convert fail");
        }
    }

    /**
     * 将str转换为map对象
     *
     * @param data          待转换的数据
     * @param kClass        key的泛型类
     * @param vClass        value的泛型类
     * @param <K>           泛型
     * @param <V>           泛型
     * @return              map对象
     */
    public static <K, V> Map<K, V> parseMap(String data, Class<K> kClass, Class<V> vClass) {
        JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(HashMap.class, kClass, vClass);
        return parseJavaType(data, javaType);
    }

    /**
     * 将str转换为list对象
     *
     * 不支持符合泛型
     *
     * @param data          待转换的数据
     * @param tClass        目标泛型类
     * @param <T>           泛型
     * @return              输出list
     */
    public static <T> List<T> parseList(String data, Class<T> tClass) {
        JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, tClass);
        return parseJavaType(data, javaType);
    }

    /**
     * 指定泛型转换
     *
     * @param data          待转换的数据
     * @param javaType      将泛型封装成JavaType
     * @param <T>           返回的泛型
     * @return              泛型集合对象
     */
    private static <T> T parseJavaType(String data, JavaType javaType) {
        try {
            return OBJECT_MAPPER.readValue(data, javaType);
        } catch (IOException e) {
            throw new BaseException(e, "JSON convert fail");
        }
    }
}
